<template>
  <div class="map-container">
    <div class="map-header">
      <ElInput
        v-model="searchKeyword"
        placeholder="输入地点名称，如'天安门'"
        clearable
        @keydown.enter.prevent.native="handleSearch"
        @keyup.enter.prevent.native="handleSearch"
        class="search-input"
        @clear="handleClearSearch"
      >
        <template #append>
          <ElButton type="primary" @click="handleSearch" icon="Search"
            >搜索</ElButton
          >
        </template>
      </ElInput>
      <!-- 添加手动定位按钮 -->
      <ElButton
        type="primary"
        @click="triggerGeolocation"
        icon="Location"
        class="locate-button"
      >
        定位
      </ElButton>
    </div>
    <div id="map-container" ref="mapContainer"></div>

    <div class="search-results" v-show="searchResults.length > 0 || isLoading">
      <ElCard shadow="hover">
        <template #header>
          <div class="flex items-center justify-between">
            <h3>搜索结果</h3>
            <ElIcon v-if="isLoading" class="is-loading">
              <Loading />
            </ElIcon>
          </div>
        </template>
        <ElScrollbar height="300px">
          <template v-if="!isLoading">
            <div
              v-for="(item, index) in searchResults"
              :key="index"
              class="result-item"
              @click="centerToLocation(item)"
            >
              <div class="result-name">
                <ElIcon class="location-icon">
                  <Location />
                </ElIcon>
                {{ item.name }}
              </div>
              <div class="result-address">{{ item.address }}</div>
              <div class="result-distance" v-if="item.distance">
                <ElIcon>
                  <Position />
                </ElIcon>
                距离: {{ (item.distance / 1000).toFixed(1) }}公里
              </div>
            </div>
          </template>
          <div v-else class="loading-text">搜索中...</div>
        </ElScrollbar>
      </ElCard>
    </div>
  </div>
</template>
<script type="text/javascript">
// 必须在AMap JS加载前设置安全配置
window._AMapSecurityConfig = {
  securityJsCode: mapSetting.mapSecurity || "",
};
</script>
<script setup>
import {
  ref,
  onMounted,
  onBeforeUnmount,
  watch,
  computed,
  defineProps,
  defineEmits,
} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import {
  ElMessage,
  ElInput,
  ElButton,
  ElScrollbar,
  ElCard,
  ElIcon,
} from "element-plus";
import { Loading, Location, Position } from "@element-plus/icons-vue";
import { mapSetting } from "#/api/map";

// 地图实例
const map = ref(null);
const mapContainer = ref(null);
const placeSearch = ref(null);
const marker = ref(null);
const point = ref([]);
const geocoder = ref();
const AMapInstance = ref(null); // 保存AMap实例
const geolocationControl = ref(null);

const props = defineProps({
  data: {
    type: Object,
    default: () => ({
      defaultAddress: "",
      defaultPoint: [],
    }),
  },
});

// 计算属性获取点坐标
const defaultPoint = computed(
  () => props.data?.defaultPoint || [116.397428, 39.90923]
);
const defaultAddress = computed(() => props.data?.defaultAddress || "");

const emits = defineEmits(["getPosition"]);

// 搜索相关
const searchKeyword = ref("");
const searchResults = ref([]);
const address = ref(""); // 地址

// 改进的定位功能实现
// 修改initGeolocation函数
const initGeolocation = () => {
  if (!map.value || !AMapInstance.value) return;

  const geolocation = new AMapInstance.value.Geolocation({
    enableHighAccuracy: true,
    timeout: 15000,
    maximumAge: 300000,
    convert: true,
    showButton: true,
    buttonPosition: "RB",
    buttonOffset: new AMapInstance.value.Pixel(10, 20),
    showMarker: true,
    showCircle: true,
    panToLocation: true,
    zoomToAccuracy: true,
  });

  map.value.addControl(geolocation);
  
  // 保存定位控件引用
  geolocationControl.value = geolocation;

  // 使用更安全的方式添加事件监听
  if (AMapInstance.value.Event) {
    // 如果AMap.Event存在，使用它
    AMapInstance.value.Event.addListener(geolocation, "complete", (result) => {
      console.log("定位成功:", result);
      handleGeolocationSuccess(result);
    });

    AMapInstance.value.Event.addListener(geolocation, "error", (error) => {
      console.error("定位失败1:", error);
      handleGeolocationError(error);
      fallbackToIPGeolocation();
    });
  } else if (AMapInstance.value.event) {
    // 如果amap.event存在（小写），使用它
    AMapInstance.value.event.addListener(geolocation, "complete", (result) => {
      console.log("定位成功:", result);
      handleGeolocationSuccess(result);
    });

    AMapInstance.value.event.addListener(geolocation, "error", (error) => {
      console.error("定位失败2:", error);
      handleGeolocationError(error);
      fallbackToIPGeolocation();
    });
  } else {
    // 如果都没有，使用控件自带的事件方法（如果存在）
    if (geolocation.on) {
      geolocation.on("complete", (result) => {
        console.log("定位成功:", result);
        handleGeolocationSuccess(result);
      });

      geolocation.on("error", (error) => {
        console.error("定位失败3:", error);
        handleGeolocationError(error);
        fallbackToIPGeolocation();
      });
    } else {
      // 最后的备选方案：使用setTimeout定期检查位置
      console.warn("无法绑定事件监听器，将使用备选方案");
      setTimeout(() => {
        // 这里可以添加备选逻辑
      }, 1000);
    }
  }

  return geolocation;
};

// 定位成功处理函数
const handleGeolocationSuccess = (result) => {
  ElMessage.success("定位成功");
  // 更新当前点位置
  point.value = [result.position.lng, result.position.lat];
  // 添加标记
  addMarker();
  // 获取地址信息
  getAddress();
};

// 定位失败处理函数
const handleGeolocationError = (error) => {
  ElMessage.error("定位失败4: " + error.message);
};

// 备选方案：使用IP定位
const fallbackToIPGeolocation = () => {
  if (!AMapInstance.value) return;

  // 使用高德地图的IP定位插件
  AMapInstance.value.plugin(["AMap.CitySearch"], () => {
    const citySearch = new AMapInstance.value.CitySearch();
    citySearch.getLocalCity((status, result) => {
      if (status === "complete" && result.info === "OK") {
        // 查询成功，result即为当前城市信息
        const city = result.city;
        // 使用城市名进行地理编码获取中心点
        if (geocoder.value) {
          geocoder.value.getLocation(city, (status, result) => {
            if (status === "complete" && result.geocodes.length) {
              const location = result.geocodes[0].location;
              point.value = [location.lng, location.lat];
              map.value.setCenter(point.value);
              addMarker();
              ElMessage.info("已定位到您所在城市: " + city);
            }
          });
        }
      } else {
        // 定位失败
        ElMessage.warning("无法获取您的位置信息，请手动选择地点");
      }
    });
  });
};

// 手动触发定位的方法
// 手动触发定位的方法
const triggerGeolocation = () => {
  if (!map.value || !AMapInstance.value) return;

  // 如果已有定位控件，直接使用它获取位置
  if (geolocationControl.value) {
    geolocationControl.value.getCurrentPosition((status, result) => {
      if (status === "complete") {
        handleGeolocationSuccess(result);
      } else {
        handleGeolocationError(result);
        fallbackToIPGeolocation();
      }
    });
  } else {
    // 如果没有定位控件，创建一个临时的
    const geolocation = new AMapInstance.value.Geolocation({
      enableHighAccuracy: true,
      timeout: 15000,
      maximumAge: 300000,
      convert: true,
      showButton: false, // 不显示按钮
      showMarker: true,
      showCircle: true,
      panToLocation: true,
      zoomToAccuracy: true
    });

    geolocation.getCurrentPosition((status, result) => {
      if (status === "complete") {
        handleGeolocationSuccess(result);
      } else {
        handleGeolocationError(result);
        fallbackToIPGeolocation();
      }
    });
  }
};

// 初始化地图
// 初始化地图
const initMap = async () => {
  try {
    const AMap = await AMapLoader.load({
      key: mapSetting.mapKey,
      securityJsCode: mapSetting.mapSecurity,
      version: "2.0",
      plugins: [
        "AMap.PlaceSearch",
        "AMap.Geocoder",
        "AMap.AutoComplete",
        "AMap.ToolBar",
        "AMap.Scale",
        "AMap.Marker",
        "AMap.Geolocation",
        "AMap.Event"  // 确保事件模块被加载
      ],
    });

    // 保存AMap实例以便在其他函数中使用
    AMapInstance.value = AMap;
    point.value = defaultPoint.value;
    const center = defaultPoint.value?.[0]
      ? defaultPoint.value
      : [116.397428, 39.90923];
    // 创建地图实例
    map.value = new AMap.Map(mapContainer.value, {
      zoom: 13,
      center,
      viewMode: "2D",
    });
    // 初始化地点搜索
    placeSearch.value = new AMap.PlaceSearch({
      map: map.value,
      pageSize: 10,
      pageIndex: 1,
      city: "全国",
    });
    // 初始化地理编码器
    geocoder.value = new AMap.Geocoder({
      city: "010",
      radius: 1000,
    });
    
    // 初始化定位（替换原来的定位代码）
    initGeolocation();

    addMarker();
    // 地图点击事件
    map.value.on("click", clickMapHandler);
  } catch (error) {
    console.error("地图初始化失败:", error);
  }
};

// 执行搜索
const isLoading = ref(false);
const handleClearSearch = () => {
  searchResults.value = [];
  searchKeyword.value = "";
  isLoading.value = false;
};

const handleSearch = () => {
  const keyword = searchKeyword.value.trim();
  if (!keyword) {
    ElMessage.warning("请输入搜索关键词");
    return;
  }

  isLoading.value = true;
  searchResults.value = [];

  // 设置PlaceSearch的事件监听
  if (placeSearch.value) {
    try {
      // 使用更安全的方式检查事件模块
      let eventModule = null;
      if (AMapInstance.value.Event) {
        eventModule = AMapInstance.value.Event;
      } else if (AMapInstance.value.event) {
        eventModule = AMapInstance.value.event;
      }

      if (eventModule) {
        // 移除之前的事件监听（如果有）
        try {
          eventModule.removeListener(placeSearch.value, "markerClick");
        } catch (error) {
          console.warn("移除事件监听失败，可能是之前没有添加过:", error);
        }
        // 添加标记点击事件
        eventModule.addListener(placeSearch.value, "markerClick", (e) => {
          if (e && e.data) {
            const poi = e.data;
            // 更新搜索框
            searchKeyword.value = poi.name;
            // 保存位置信息
            const markerPosition = [poi.location.lng, poi.location.lat];
            point.value = markerPosition;
            // 获取地址信息
            getAddress();
            // 关闭搜索结果面板
            searchResults.value = [];
          }
        });
      } else {
        // 备用方法：在搜索完成后，为所有标记添加点击事件
        setTimeout(() => {
          if (map.value && typeof map.value.getAllOverlays === 'function') {
            const markers = map.value.getAllOverlays("marker");
            markers.forEach((marker) => {
              // 为每个标记添加点击事件
              if (marker.on) {
                marker.on("click", (e) => {
                  // 获取标记的位置
                  const position = marker.getPosition();
                  const markerPosition = [position.getLng(), position.getLat()];
                  // 更新当前位置
                  point.value = markerPosition;
                  // 移动地图中心点
                  map.value.setCenter(markerPosition);
                  // 获取地址信息
                  getAddress();
                  // 尝试查找与此标记位置匹配的搜索结果
                  const matchingResult = searchResults.value.find((item) => {
                    const itemLng = item.location.lng;
                    const itemLat = item.location.lat;
                    // 使用近似比较，因为浮点数可能有微小差异
                    return (
                      Math.abs(itemLng - position.getLng()) < 0.0001 &&
                      Math.abs(itemLat - position.getLat()) < 0.0001
                    );
                  });
                  // 如果找到匹配的搜索结果，更新搜索框
                  if (matchingResult) {
                    searchKeyword.value = matchingResult.name;
                  }
                  // 关闭搜索结果面板
                  searchResults.value = [];
                });
              }
            });
          }
        }, 500);
      }
    } catch (error) {
      console.error("设置PlaceSearch事件监听失败:", error);
    }
  }

  // 执行搜索
  placeSearch.value.search(keyword, (status, result) => {
    isLoading.value = false;

    if (status === "complete" && result.poiList?.pois) {
      searchResults.value = result.poiList.pois;
      if (searchResults.value.length === 0) {
        ElMessage.info("未找到相关地点");
      }
    } else {
      const errorMsg = result?.info || "搜索失败";
      ElMessage.error(errorMsg);
      console.error("搜索出错:", errorMsg);
      searchResults.value = [];
    }
  });
};

// 将经纬度转换为地址
const getAddress = () => {
  geocoder.value.getAddress(point.value, (status, result) => {
    if (status === "complete" && result.regeocode) {
      address.value = result.regeocode.formattedAddress;
      emits("getPosition", {
        defaultAddress: result.regeocode.formattedAddress,
        defaultPoint: point.value,
      });
    } else {
      let errorMsg = "地理编码失败";
      if (result?.info === "INVALID_USER_KEY") {
        errorMsg = "高德地图API密钥无效，请检查配置";
      } else if (result?.info === "DAILY_QUERY_OVER_LIMIT") {
        errorMsg = "高德地图API调用已达日限额";
      }
      ElMessage.error(errorMsg);
      console.error("地理编码失败", result);
    }
  });
};

// 增加点标记
const addMarker = () => {
  // 清除其他icon
  if (marker.value) {
    marker.value.setMap(null);
    marker.value = null;
  }
  // 重新渲染icon
  marker.value = new AMapInstance.value.Marker({
    position: point.value, // icon经纬度
    offset: new AMapInstance.value.Pixel(-13, -30), // icon中心点的偏移量
    icon: new AMapInstance.value.Icon({
      image:
        "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
      size: new AMapInstance.value.Size(30, 40), // 图标大小
      imageSize: new AMapInstance.value.Size(30, 40),
    }),
    clickable: true, // 确保标记可点击
    cursor: "pointer", // 鼠标悬停时显示手型光标
  });
  marker.value.setMap(map.value); // 设置icon
};

const clickMapHandler = (e) => {
  const lng = e.lnglat.lng;
  const lat = e.lnglat.lat;
  point.value = [lng, lat];
  map.value?.setCenter(point.value);
  // 增加点标记
  addMarker();
  getAddress();
};

// 定位到指定位置
const centerToLocation = (poi) => {
  searchResults.value = [];
  isLoading.value = false;
  if (!map.value) return;

  // 清除旧标记
  if (marker.value) {
    map.value.remove(marker.value);
    marker.value = null;
  }

  // 保存位置信息，以便在点击事件中使用
  const markerPosition = [poi.location.lng, poi.location.lat];

  // 创建新标记，并在创建时直接绑定点击事件
  if (AMapInstance.value) {
    marker.value = new AMapInstance.value.Marker({
      position: markerPosition,
      map: map.value,
      clickable: true, // 确保标记可点击
      cursor: "pointer", // 鼠标悬停时显示手型光标
      bubble: false, // 关闭事件冒泡，防止点击事件被地图捕获
    });
  } else {
    console.error("AMap实例不可用，无法创建标记");
    return;
  }

  // 移动地图中心点
  map.value.setCenter(markerPosition);
  map.value.setZoom(15);
  searchKeyword.value = poi.name;
  emits("getPosition", {
    defaultAddress: poi.name,
    defaultPoint: markerPosition,
  });
};

const isMounted = ref(false);

// 监听props.data变化
watch(
  () => props.data,
  (newVal) => {
    if (isMounted.value && newVal?.defaultPoint) {
      if (map.value) {
        // 已有地图实例则更新中心点
        map.value.setCenter(newVal.defaultPoint);
        point.value = newVal.defaultPoint;
        addMarker();
      } else {
        // 无地图实例则初始化
        initMap();
      }
    }
  },
  { deep: true, immediate: true }
);

onMounted(() => {
  isMounted.value = true;
  // 确保有默认值才初始化
  if (props.data.defaultPoint && props.data.defaultPoint.length === 2) {
    initMap();
  } else {
    console.warn("等待有效的地图中心点坐标");
  }
});

onBeforeUnmount(() => {
  // 清理地图
  if (map.value) {
    map.value.destroy();
  }
});
</script>

<style scoped>
.map-container {
  position: relative;
  width: 100%;
  height: 400px;
}

#map-container {
  width: 100%;
  height: 100%;
}

.map-header {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 999;
  width: 400px;
  display: flex;
  gap: 10px;
}

.search-input {
  border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
  box-shadow: 0 2px 6px rgb(0 0 0 / 30%);
  flex: 1;
}

.locate-button {
  height: 32px;
  align-self: center;
}

.search-results {
  position: absolute;
  top: 60px;
  left: 20px;
  z-index: 999;
  width: 400px;
}

.result-item {
  padding: 12px 16px;
  cursor: pointer;
  border-bottom: 1px solid var(--el-border-color-light);
  transition: all 0.3s ease;
}

.result-item:hover {
  background-color: var(--el-color-primary-light-9);
  transform: translateX(4px);
}

.result-name {
  display: flex;
  align-items: center;
  font-weight: bold;
  color: var(--el-text-color-primary);
}

.location-icon {
  margin-right: 8px;
  color: var(--el-color-primary);
}

.result-address {
  margin-left: 24px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.result-distance {
  display: flex;
  align-items: center;
  margin-left: 24px;
  font-size: 12px;
  color: var(--el-color-primary);
}

.result-distance .el-icon {
  margin-right: 4px;
}

.loading-text {
  padding: 20px;
  color: var(--el-text-color-secondary);
  text-align: center;
}

:deep(.el-card__body) {
  padding: 0;
}
</style>
